/**
 * File Name	: DateTime.h
 * Location		: /Core/
 * Lib.Name		: Core.a
 * Designer		: OS (20-09-06)
 * Mod. 1 by	: AS (25-09-06)
 */

#pragma once

namespace Core
{
	class DateTime
	{
	private:
		unsigned long m_Seconds; ///Seconds since 1-1-1970 (epoch time)

	public:
		/**
	 	 * Default constructor, mengembalikan waktu saat ini 
	 	 */
		DateTime(); ///Now!
	
		/**
	 	 * Constructor, mengembalikan waktu sesuai parameter p_Seconds
		 * @param p_Seconds detik sejak 1-1-1970
	 	 */
		DateTime(unsigned long p_Seconds);
	
		/**
	 	 * Constructor, mengembalikan waktu sesuai parameter masukan
		 * @param p_Year tahun, jika KURANG dari 1900 maka dianggap tahun saat ini
		 * @param p_Month bulan, jika LEBIH dari 11 maka dianggap bulan saat ini
		 * @param p_Date tanggal dalam bulan tertentu, jika TIDAK DIANTARA 1 sampai 31 maka dianggap tanggal saat ini
		 * @param p_Hour jam, jika LEBIH DARI 23 maka dianggap jam saat ini
		 * @param p_Minute menit, jika LEBIH DARI 59 maka dianggap menit saat ini
		 * @param p_Second detik, jika LEBIH DARI 59 maka dianggap detik saat ini
	 	 */
		DateTime(unsigned short p_Year, unsigned char p_Month, unsigned char p_Date,
			unsigned char p_Hour, unsigned char p_Minute, unsigned char p_Second);
			
		/**
	 	 * Mengembalikan objek DateTime yang merupakan selisih dua buah DateTime
		 * @param p_DateTime objek DateTime yang akan dihitung selisihnya
		 * @return selisih dua buah DateTime
	 	 */
		long Delta(DateTime p_DateTime);
		
		/**
	 	 * Mengembalikan tahun dari objek DateTime
		 * @return tahun
	 	 */
		unsigned short GetYear();
		
		/**
	 	 * Mengembalikan bulan semenjak bulan January dari objek DateTime (0-11)
		 * @return bulan
	 	 */
		unsigned char GetMonth();
		
		/**
	 	 * Mengembalikan tanggal dalam bulan (day of month) dari objek DateTime (1-31)
		 * @return tanggal
	 	 */
		unsigned char GetDate();
		
		/**
	 	 * Mengembalikan hari semenjak hari minggu dari objek DateTime, yaitu 0(minggu)-6(sabtu)
		 * @return hari semenjak hari minggu
	 	 */
		unsigned char GetDay();
		
		/**
	 	 * Mengembalikan jam dari objek DateTime (0-23)
		 * @return jam
	 	 */
		unsigned char GetHour();
		
		/**
	 	 * Mengembalikan menit dari objek DateTime (0-59)
		 * @return menit
	 	 */
		unsigned char GetMinute();
		
		/**
	 	 * Mengembalikan detik dari objek DateTime (0-61)
		 * @return detik
	 	 */
		unsigned char GetSecond();
		
		/**
	 	 * Mengembalikan total detik objek DateTime sejak 1 January 1970
		 * @return menit
	 	 */
		unsigned long GetTotalSeconds();
		
		/**
	 	 * Mengubah tahun dari objek DateTime
		 * @param p_Year tahun yang baru (>=1900)
	 	 */
		void SetYear(unsigned short p_Year);
		
		/**
	 	 * Mengubah bulan dari objek DateTime
		 * @param p_Month bulan yang baru (0-11)
	 	 */
		void SetMonth(unsigned char p_Month);
		
		/**
	 	 * Mengubah tanggal dari objek DateTime
		 * @param p_Date tanggal yang baru (1-31)
	 	 */
		void SetDate(unsigned char p_Date);
		
		/**
	 	 * Mengubah jam dari objek DateTime
		 * @param p_Hour jam yang baru (0-23)
	 	 */
		void SetHour(unsigned char p_Hour);
		
		/**
	 	 * Mengubah menit dari objek DateTime
		 * @param p_Minute menit yang baru (0-59)
	 	 */
		void SetMinute(unsigned char p_Minute);
		
		/**
	 	 * Mengubah detik dari objek DateTime
		 * @param p_Second detik yang baru (0-61)
	 	 */
		void SetSecond(unsigned char p_Second);
		
		/**
	 	 * Mengembalikan true jika kedua objek DateTime menyatakan waktu yang sama
		 * @return true jika kedua DateTime menyatakan waktu yang sama, false jika sebaliknya
	 	 */
		bool operator==(DateTime& p_DateTime);
		
		/**
	 	 * Mengembalikan true jika objek DateTime pertama memiliki total waktu 
		 * semenjak 1-1-1970 yang lebih besar daripada objek DateTime kedua
		 * @return true jika objek pertama lebih besar dari objek kedua, false jika sebaliknya
	 	 */
		bool operator>(DateTime& p_DateTime);
		
		/**
	 	 * Mengembalikan true jika objek DateTime pertama memiliki total waktu 
		 * semenjak 1-1-1970 yang lebih besar atau sama dengan objek DateTime kedua
		 * @return true jika objek pertama lebih besar atau sama dengan objek kedua, false jika sebaliknya
	 	 */
		bool operator>=(DateTime& p_DateTime);
		
		/**
	 	 * Mengembalikan true jika objek DateTime pertama memiliki total waktu 
		 * semenjak 1-1-1970 yang lebih kecil daripada objek DateTime kedua
		 * @return true jika objek pertama lebih kecil dari objek kedua, false jika sebaliknya
	 	 */
		bool operator<(DateTime& p_DateTime);
		
		/**
	 	 * Mengembalikan true jika objek DateTime pertama memiliki total waktu 
		 * semenjak 1-1-1970 yang lebih kecil atau sama dengan objek DateTime kedua
		 * @return true jika objek pertama lebih kecil atau sama dengan objek kedua, false jika sebaliknya
	 	 */
		bool operator<=(DateTime& p_DateTime);
		
		/**
	 	 * Mengubah objek DateTime menjadi std::string dengan format tertentu. 
		 * Format yang dapat digunakan:
		 * 	Code  	Meaning
		 *  ====================================================================
		 *	%a 		abbreviated weekday name (e.g. Fri)
		 *	%A 		full weekday name (e.g. Friday)
		 *	%b 		abbreviated month name (e.g. Oct)
		 *	%B 		full month name (e.g. October)
		 *	%c 		the standard date and time std::string
		 *	%d 		day of the month, as a number (1-31)
		 *	%H 		hour, 24 hour format (0-23)
		 *	%I 		hour, 12 hour format (1-12)
		 *	%j 		day of the year, as a number (1-366)
		 *	%m 		month as a number (1-12). Note: some versions of Microsoft Visual C++ may use values that range from 0-11.
		 *	%M 		minute as a number (0-59)
		 *	%p 		locale's equivalent of AM or PM
		 *	%S 		second as a number (0-59)
		 *	%U 		week of the year, (0-53), where week 1 has the first Sunday
		 *	%w 		weekday as a decimal (0-6), where Sunday is 0
		 *	%W 		week of the year, (0-53), where week 1 has the first Monday
		 *	%x 		standard date std::string
		 *	%X 		standard time std::string
		 *	%y 		year in decimal, without the century (0-99)
		 *	%Y 		year in decimal, with the century
		 *	%Z 		time zone name
		 *	%% 		a percent sign
		 * @param p_Format format output yang diinginkan sesuai dengan ketentuan diatas
		 * @return objek std::string yang sesuai dengan format yang diberikan
	 	 */
		std::string ToString(std::string p_Format="");
		
		/**
	 	 * Meng-output-kan objek DateTime ke objek ostream, dengan format standard ("%A, %d %B %Y, %I:%M:%S %p").
		 * @param p_Out objek ostream yang menerima output
		 * @param p_DateTime objek DateTime yang akan di-output-kan
		 * @return objek ostream
	 	 */
		friend std::ostream& operator<<(std::ostream& p_Out, DateTime& p_DateTime);
	};

	/**
	 * Meng-output-kan objek DateTime ke objek ostream, dengan format standard ("%A, %d %B %Y, %I:%M:%S %p").
	 * @param p_Out objek ostream yang menerima output
	 * @param p_DateTime objek DateTime yang akan di-output-kan
	 * @return objek ostream
	 */
	 std::ostream& operator<<(std::ostream& p_Out, DateTime& p_DateTime);
}

/**
 * Petunjuk: gunakan library pada std c++ seperti: localtime untuk mendapatkan
 * tahun hingga detik saat ini, dan gunakan fungsi GetTime pada kelas Core::System
 * untuk mendapatkan jumlah detik semenjak EPOCH yang merupakan masukan fungsi-fungsi
 * library std c++
 */
